# _*_ coding:utf-8 _*_
# @File  : index_analysis.py
# @Time  : 2022-06-11
# @Author: zizle
from typing import Union
import numpy as np
from fastapi import APIRouter, Body
from pydantic import BaseModel, datetime_parse
from v1_all_api.all_response import AllResponse
from v1_all_api.all_utils import datalib_utils, datetime_utils

# 指标数据分析
index_analysis_api = APIRouter()


class FormulaItem(BaseModel):
    query_date: datetime_parse.date
    id: int
    formula: str
    frequency: str
    unit: str = ''
    index_name: str = ''


@index_analysis_api.post('/linkRatio/')  # 根据指标公式,求出数据的最新和环比变化值
async def index_formula_link_ratio(formula_item: FormulaItem = Body(...)):
    formula_dict = {
        'id': formula_item.id,
        'formula': formula_item.formula,
        'frequency': formula_item.frequency,
        'unit': formula_item.unit,
        'name': formula_item.index_name
    }
    # 通过公式获取数值
    df, table_headers = await datalib_utils.get_index_formula_dataframe(column_templates=[formula_dict],
                                                                        na_fill=np.NAN)
    # 取数据计算环比数
    df = df[df['datadate'] <= formula_item.query_date]
    df = df.tail(5)
    # 将c_0列改为value列
    df.rename(columns={'c_0': 'value'}, inplace=True)  # 这里肯定是c_0，因为只有一个计算公式
    df['diff'] = df['value'].diff().round(2)  # 计算差值并保留2位小数
    df['value'] = df['value'].round(2)  # 数值保留2位小数
    df.fillna('NAN', inplace=True)

    pre_cur_data = df.tail(2).to_dict(orient="records")
    if len(pre_cur_data) < 2:
        cur_data = pre_cur_data[0]
        pre_data = cur_data
    else:
        pre_data, cur_data = pre_cur_data

    pre_date = pre_data['datadate']
    pre_value = pre_data['value']
    pre_diff = pre_data['diff']

    cur_date = cur_data['datadate']
    cur_value = cur_data['value']
    cur_diff = cur_data['diff']
    # #############
    delta_days = (formula_item.query_date - cur_date).days  # 实际查询日期与最新数据的间隔
    avail_days = datetime_utils.frequency_delta_days(cur=formula_item.query_date, frequency=formula_item.frequency)  # 查询日时可用的上期数据间隔
    conditions = {'日': 1, '周': 7, '月': 31, '季': 93, '年': 366}
    is_far = False
    if delta_days > avail_days:  # 超出周期范围
        pre_date = cur_date
        pre_value = cur_value
        pre_diff = cur_diff
        cur_value = 'NAN'
        cur_diff = 'NAN'
        is_far = (delta_days - avail_days) > conditions.get(formula_item.frequency, 365)

    # conditions = {'日': 0, '周': 11, '月': 62, '季': 180, '年': 732}  # 除了日以外，其他日期都可以使用上一时间的数据
    # if delta_days > conditions.get(formula_item.frequency, 9999):
    #     pre_date = cur_date
    #     pre_value = cur_value
    #     pre_diff = cur_diff
    #     cur_value = 'NAN'
    #     cur_diff = 'NAN'

    formula_dict['index_name'] = formula_dict['name']
    del formula_dict['name']
    response_data = {
        **formula_dict,
        'pre_date': pre_date,
        'pre_value': pre_value,
        'pre_diff': pre_diff,
        'datadate': cur_date,
        'value': cur_value,
        'diff': cur_diff,
        'is_far': is_far
    }
    return AllResponse.operate_successfully(data=response_data)


class BodyFormula(BaseModel):
    formula: str
    na_fill: Union[float, str] = ''


@index_analysis_api.post('/formulaData/')  # 根据指标公式,得到数据
async def formula_data(body: BodyFormula = Body(...)):
    # 验证公式
    if not datalib_utils.formula_is_correct(body.formula):
        return AllResponse.validate_error(msg='formula is incorrect!')
    formula_dict = {
        'formula': body.formula
    }
    # 通过公式获取数值
    df, table_headers = await datalib_utils.get_index_formula_dataframe(column_templates=[formula_dict],
                                                                        na_fill=np.NAN)
    df.rename(columns={'c_0': 'datavalue'}, inplace=True)  # 只有一列数据肯定为c_0
    df.fillna(body.na_fill, inplace=True)
    return AllResponse.operate_successfully(
        data={'formula': body.formula, 'na_fill': body.na_fill, 'data': df.to_dict(orient='records')})
